package org.springframework.beans.factory.support;

import cn.hutool.core.bean.BeanException;
import cn.hutool.core.bean.BeanUtil;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;

/**
 * @author 山顶洞人郑某
 * @className AbstractAutowireCapableBeanFactory.java 抽象自动装配Bean工厂
 * 主要用于管理 Bean 的实例化、配置和生命周期。
 *  @date 2025 04 21
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{

    private InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();
    /**
     * 创建bean
     * @param beanName bean的名称
     * @param beanDefinition bean的基本信息
     * @return bean对象
     */
    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeanException {
        return doCreateBean(beanName,beanDefinition);
    }

    /**
     * 创建 bean
     * @param beanName
     * @param beanDefinition
     * @return
     */
    @SuppressWarnings("all")
    protected Object doCreateBean(String beanName, BeanDefinition beanDefinition)   {
        Class beanClass = beanDefinition.getBeanClass();
        Object bean = null;
        try {
            //创建bean对象
            bean = createBeanInstance(beanDefinition);
            //给bean填充属性
            applyPropertyValues(bean,beanName,beanDefinition.getPropertyValues());
        } catch (Exception e) {
            throw new BeanException("创建 bean 失败",e);
        }
        //将bean放入bean容器中
        addSingleton(beanName,bean);
        return bean;
    }

    /**
     * 给bean填充属性
     * @param bean
     * @param beanName
     * @param propertyValues
     */
    protected void applyPropertyValues(Object bean,String beanName, PropertyValues propertyValues) {
       try {
           for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
               //如果属性值为一个Bean对象 则先创建Bean对象 再赋值
               Object value = propertyValue.getValue();
               if (value instanceof BeanReference ) {
                   BeanReference beanReference = (BeanReference) value;
                   value = getBean(beanReference.getBeanName());
               }
               BeanUtil.setFieldValue(bean, propertyValue.getName(), value);
           }
       } catch (Exception e) {
           throw new BeanException("设置bean属性失败：" + beanName, e);
       }
    }

    /**
     * 实例化bean
     *
     * @param beanDefinition
     * @return
     */
    protected Object createBeanInstance(BeanDefinition beanDefinition) {
        return getInstantiationStrategy().instantiate(beanDefinition);
    }

    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }
}
